<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>generator函数学习</title>
</head>
<body>
	<script type="text/javascript">
		Function.prototype.myBind = function() {
			var _this = this;
			var context = [].shift.call(arguments);// 保存需要绑定的this上下文
			var args = [].slice.call(arguments); //剩下参数转为数组
			console.log(_this, context, args);
			return function() {
				return _this.apply(context, [].concat.call(args, [].slice.call(arguments)));
			}
		};
		
		/**
		 * 每个函数都可以调用call方法，来改变当前这个函数执行的this关键字，并且支持传入参数
		 */
		Function.prototype.myCall = function(context) {
			//第一个参数为调用call方法的函数中的this指向
			var context = context || global;
			//将this赋给context的fn属性
			context.fn = this;//此处this是指调用myCall的function

			var arr = [];
			for (var i=0,len=arguments.length;i<len;i++) {
				arr.push("arguments[" + i + "]");
			}
			//执行这个函数，并返回结果
			var result = eval("context.fn(" + arr.toString() + ")");
			//将this指向销毁
			delete context.fn;
			return result;
		}
		
		/**
		 * apply函数传入的是this指向和参数数组
		 */
		Function.prototype.myApply = function(context, arr) {
			var context = context || global;
			context.fn = this;
			var result;
			if (!arr) {
				result = context.fn(); //直接执行
			} else {
				var args = [];
				for (var i=0,len=arr.length;i<len;i++) {
					args.push("arr[" + i + "]");
				}
				result = eval("context.fn([" + args.toString() + "])");
			}
			//将this指向销毁
			delete context.fn;
			return result;
		}
		
		
		
		var obj = {};

		function test() {
			console.log(this === obj);
		}

		var testObj = test.bind(obj);
		testObj();  //true

		var objTest = {
			"作者": "chengbo"
		};
		/**
		 * 预期返回false, 但是testObj是个绑定函数，所以不能改变其this指向
		 */
		testObj.apply(objTest); //true
		testObj.call(objTest); //true




	</script>
</body>
</html>